<?php declare(strict_types=1);

namespace app\middleware;

use app\exception\auth\TokenExpired;
use app\exception\auth\TokenInvalidate;
use app\exception\auth\TokenRequired;
use app\library\DefaultConfig;
use app\model\UserToken;
use clonelin\library\DateTime;
use think\Middleware;
use think\Request;
use app\facade\logic\Base as FaBaseLogic;
use think\Response;


class Token extends Middleware{

    public function handle(Request $request, \Closure $next){

        /**
         * Before Middleware
         */
        // Token Must
        $token = $request->header(DefaultConfig::HEADER_TOKEN_NAME);
        if(empty($token)){
            throw new TokenRequired();
        }
        // Token Invalidate Check
        $this->tokenCheck($token);

        // Response
        return $next($request);
    }


    // Token Check
    private function tokenCheck(string $token) : ?Response {

        $tokenInfo = FaBaseLogic::getTokenByToken($token);
        // Token Invalidate
        if(empty($tokenInfo)){
            throw new TokenInvalidate();
        }

        // Token Expired Check
        $this->tokenExpired($tokenInfo['expire_at']);

        // Update Token Expire Time
        $this->tokenUpdate($tokenInfo);

        return null;
    }

    // Token Expired Check
    private function tokenExpired(string $userExpireTime) : ?Response {
        // System Expire Time
        $now = DateTime::getCurrentDateTime();
        if($userExpireTime < $now) {
            throw new TokenExpired();
        }
        return null;
    }

    // Token Update
    private function tokenUpdate(UserToken $tokenInfo,int $systemExpireTimeMinute = 20){

        $now = DateTime::getCurrentDateTime();
        $expireTime = DateTime::getAfterMinutesOfNow($systemExpireTimeMinute);
        $tokenInfo->save(['update_at'=>$now,'expire_at'=>$expireTime]);
    }

}